home *** CD-ROM | disk | FTP | other *** search
- page 60,132
-
- ;PROGRAM : IPCSAMP.ASM
- ; This program demonstrates the use of IPC in Assembly. It is
- ; self-contained in that it makes no references to external data
- ; or procedures. This sample was tested with Microsoft MACRO
- ; Assembler, version 1.27, and Borland Turbo Link, version 1.1,
- ; as follows:
- ; masm ipcsamp.asm, ipcsamp.obj, ipcsamp.lst, ipcsamp.crf
- ; tlink /m /s /n /d /c ipcsamp.obj,ipcsamp.exe,ipcsamp.map
- ; ipcsamp [data]
- ;
- ; IPCSAMP initially determines whether IPC is installed by two steps.
- ; First, if IPC's default interrupt vector (60h) is 0000:0000, IPC is
- ; not installed. Second, a call is made to the interrupt routine and
- ; the value returned in param.status is checked. If status is not
- ; INSTALLED and ENABLED, IPC is not installed.
- ;
- ; IPCSAMP next checks the command line for data to be passed to IPC.
- ; If no data is present, a default string is used.
- ;
- ; The data is sent to IPC and the return status checked. If no errors
- ; occured, the data is retrieved and displayed on the standard output.
- ;
-
- ;EQUATES
- S_ID EQU 0 ; sending process id
- R_ID EQU 0 ; receiving process id
- CMND_INQ EQU 1 ; IPC_CMND_INQUIRE
- CMND_RDATA EQU 6 ; IPC_CMND_RDATA
- CMND_SDATA EQU 7 ; IPC_CMND_SDATA
- IPC_VECTOR EQU 60h ; use default IPC vector
- ERROR_FLAG EQU 8 ; mask for return status
- INST_ENAB EQU 6 ; installed, enabled flags
- ERR_NOTINST EQU 12 ; IPC_ERR_NOTINST
- CMND_LEN_OFF EQU 080h ; offset of command length
- CMND_OFF EQU 081h ; offset of command
- CMND_LEN_MAX EQU 07Fh ; max command length
- IRET_INST EQU 0CFh ; iret instruction
- DOS_PRINT EQU 9 ; DOS print function
- TERM_PROC EQU 04Ch ; DOS terminate process function
- DOS_CALL EQU 021h ; DOS interrupt
- GET_VECT EQU 035h ; DOS get interrupt vector
-
- dataseg segment ;define data segment
- IPC_PARAM_BLOCK struc ;define IPC_PARAM_BLOCK structure
- my_id DW ?
- to_id DW ?
- command DW ?
- status DW ?
- error DW ?
- data_size DW ?
- data_ptr DD ?
- IPC_PARAM_BLOCK ends
- param IPC_PARAM_BLOCK <0,0,0,0,0,0,0> ; var of type IPC_PARAM_BLOCK
-
- ;declare a data buffer of 128 bytes
- buf_struct struc
- string DB CMND_LEN_MAX+1 dup (0)
- buf_struct ends
- buffer buf_struct <>
-
- ; declare a string of default data
- my_data DB "Toto, I don't think we're in Kansas anymore!", 13
- str_length DW 45 ; string length
-
- ; error messages and codes
- badcmnd_str DB '001: Invalid command.$'
- inst0_str DB '002: Only process 0 can install / reset PC-IPC.$'
- cantenab_str DB '003: Only the disabling process can re-enable.$'
- notenab_str DB '004: IPC is currently disabled.$'
- cantdisab_str DB '005: This process cannot disable IPC.$'
- badtoid_str DB '006: The to-process id is not valid.$'
- badfmid_str DB '007: The from-process id is not valid.$'
- noaddr_str DB '008: Invalid target address for data.$'
- maxids_str DB '009: All available process ids are in use.$'
- cantreli_str DB '010: That process id cannot be relinquished.$'
- nomem_str DB '011: Insufficient memory available for message.$'
- notinst_str DB '012: IPC is not installed. Run IPCINST.COM.$'
-
- badcmnd DW offset badcmnd_str
- inst0 DW offset inst0_str
- cantenab DW offset cantenab_str
- notenab DW offset notenab_str
- cantdisab DW offset cantdisab_str
- badtoid DW offset badtoid_str
- badfmid DW offset badfmid_str
- noaddr DW offset noaddr_str
- maxids DW offset maxids_str
- cantreli DW offset cantreli_str
- nomem DW offset nomem_str
- notinst DW offset notinst_str
- dataseg ends
-
- stakseg segment stack ; define stack segment
- DB 20 dup ('stack ')
- stakseg ends
-
- progseg segment ; define code segment
- s_data_asm proc far ; declare as a far proc
- assume cs:progseg, ds:dataseg
-
- start: ; starting execution address
-
- ; set up stack for return to DOS
- push ds ; save old data segment
- sub ax,ax ; put 0 in AX
- push ax ; save it on stack
- push ds ; save the PSP segment
-
- ; set up data segment
- mov ax, dataseg
- mov ds, ax
-
- ; verify that IPC is installed
- mov ah, GET_VECT ; get the vector,
- mov al, IPC_VECTOR ; returned in ES:BX
- int dos_call
- mov ax, es
- cmp ax, 0 ; if vector is 0000:0000
- jne inquire_ipc ; IPC is not installed
- cmp bx, 0
- jne inquire_ipc
-
- pop ds ; (to balance stack)
- mov ax, ERR_NOTINST ; print error msg and exit
- jmp err_print
-
- inquire_ipc:
- mov param.command, CMND_INQ ; init command to inquire
- mov param.status, 0 ; clear status field
-
- ; call IPC, equivalent to pc_ipc(vector, param_ptr)
- push ds
- mov ax, offset param.my_id
- push ax
- int IPC_VECTOR ; call IPC
- add sp, 4 ; clean up stack
-
- ; check return status
- mov ax, param.status ; check that IPC is
- cmp ax, INST_ENAB ; installed, enabled
- jz get_params
-
- pop ds ; (to balance stack)
- mov ax, ERR_NOTINST ; print error msg and exit
- jmp err_print
-
- ; get a copy of the data (if any) from the DOS command line
- ; The command line parameters are located in the Program Segment Prefix
- ; at offset 081h (CMND_OFF). The length of the parameters is at offset
- ; 080h (CMND_LEN_OFF). When loaded as an .exe file, the PSP segment is
- ; automatically put in DS and ES by the loader.
-
- get_params:
- pop ds ; retore PSP segment
- mov bx, CMND_LEN_OFF ; get cmnd line length
- xor cx, cx ; clear CX
- mov cl, byte ptr [ds:bx]
- push ds ; save PSP segment
- mov ax, dataseg
- mov es, ax ; set up destination segment
- mov ds, ax ; set up source segment
- mov ax, offset buffer
- mov di, ax ; set up destination offset
- mov ax, offset my_data
- mov si, ax ; set up source offset
- cmp cx, 0 ; if length=0, use default data
- jne get_cmnd_line
-
- ; use default data
- pop ax ; discard PSP segment
- mov cx, str_length ; set up string length
- jmp move_data
-
- get_cmnd_line: ; use command line data
- mov str_length, cx ; save length for later
- pop ds ; set up source segment
- mov ax, CMND_OFF ; set up source offset
- mov si, ax
- move_data:
- cld ; copy DS:SI --> ES:DI
- rep movsb ; for CX bytes
- xor al, al ; null terminate the string
- dec di
- mov byte ptr [es:di], al
-
- ; initialize the parameter block, equivalent to init_param_block(...)
-
- init_param:
- mov ax, dataseg ; set DS to dataseg segment
- mov ds, ax
- mov param.my_id, S_ID ; init my_id
- mov param.to_id, R_ID ; init to_id
- mov param.command, CMND_SDATA ; init command to send data
- mov ax, str_length
- mov param.data_size, ax ; init data_size
- mov bx, offset param.my_id ; use BX to index param
- mov word ptr [bx+12], offset buffer ; init data_ptr offset
- mov word ptr [bx+14], ds ; init data_ptr segment
-
- ; send data to IPC
- push ds
- mov ax, offset param.my_id
- push ax
- int IPC_VECTOR
- add sp, 4 ; clean up stack
-
- ; check for success
- mov ax, param.error
- mov bx, param.status
- and bx, ERROR_FLAG
- jnz err_print
-
- ; now get the data back from IPC
- ; initialize parameter block
- mov param.my_id, S_ID ; init my_id
- mov param.command, CMND_RDATA ; init command to read data
- mov param.status, 0 ; clear status
- mov bx, offset param.my_id ; use BX to index param
- mov word ptr [bx+12], offset buffer ; init data_ptr offset
- mov word ptr [bx+14], ds ; init data_ptr segment
-
- ; get the data
- push ds
- mov ax, offset param.my_id
- push ax
- int IPC_VECTOR
- add sp, 4 ; clean up stack
-
- ; check for success
- mov ax, param.error
- mov bx, param.status
- and bx, ERROR_FLAG
- jnz err_print
-
- ; display data returned from IPC
- mov bx, offset buffer
- mov ax, param.data_size
- add bx, ax
- mov ax, '$' ; $ terminated string
- mov [bx], ax
- mov ah, DOS_PRINT ; display string function
- mov dx, offset buffer ; display string at DS:DX
- int DOS_CALL
- mov ax, param.error ; return error in ERRORLEVEL
-
- ; return to DOS
- done:
- mov ah, TERM_PROC ; DOS terminate process func
- int DOS_CALL ; al already has return code
-
- err_print:
- push ax ; save error number
- mov bx, offset badcmnd ; get first msg ptr address
- dec ax ; use cx to get msg address
- jz incr_ptr_done
- mov cx, ax ; find correct message ptr
- incr_ptr:
- add bx, 2 ; get next pointer's addr
- loop incr_ptr ; loop until done
- incr_ptr_done:
- mov ax, dataseg
- mov ds, ax
- mov dx, word ptr [ds:bx] ; get msg pointer
-
- print:
- mov ah, DOS_PRINT ; display the error msg
- int DOS_CALL
- pop ax ; return error in ERRORLEVEL
- jmp done
- s_data_asm endp ; end of module
- progseg ends ; end of code segment
- end start ; end of assembly